fn main() {
	// a slice is a part of a parent array
	// it refers to the elements between two indices separated by a .. operator
	// the right-side index must be greater than or equal to the left side index
	// if a right-side index is absent, it is assumed to be the array length
	// if a left-side index is absent, it is assumed to be 0
	nums := [0, 10, 20, 30, 40]
	println(nums[1..4]) // [10, 20, 30]
	println(nums[..4]) // [0, 10, 20, 30]
	println(nums[1..]) // [10, 20, 30, 40]

	// slices are arrays themselves, all array operations may be performed on them
	array_1 := [3, 5, 4, 7, 6]
	mut array_2 := [0, 1]
	array_2 << array_1[..3]
	println(array_2) // `[0, 1, 3, 5, 4]`
	
	// a slice is created with the smallest possible capacity(cap == len),
	// no matter what the capacity or length of the parent array is.
	// it is immediately reallocated and copied to another memory location when the size increases
	mut a := [0, 1, 2, 3, 4, 5]
	mut b := a[2..4]
	b[0] = 7   // `b[0]` is referring to `a[2]`
	println(a) // `[0, 1, 7, 3, 4, 5]`
	b << 9
	// `b` has been reallocated and is now independent from `a`
	println(a) // `[0, 1, 7, 3, 4, 5]` - no change
	println(b) // `[7, 3, 9]`
	
	// appending to the parent array may or may not make it independent from its child slices
	// the behavior depends on the parent's capacity and is predictable
	mut a_2 := []int{len: 5, cap: 6, init: 2}
	mut b_2 := a[1..4]
	a_2 << 3
	// no reallocation - fits in `cap`
	b_2[2] = 13 // `a_2[3]` is modified
	a_2 << 4
	// a_2 has been reallocated and is now independent from `b_2` (`cap` was exceeded)
	b_2[1] = 3 // no change in `a_2`
	println(a_2) // `[2, 2, 2, 13, 2, 3, 4]`
	println(b_2) // `[2, 3, 13]`
	
	// if you do want to have an independent copy, you can call .clone() on the slice
	mut a_3 := [0, 1, 2, 3, 4, 5]
	mut b_3 := a[2..4].clone()
	b_3[0] = 7 // NB: `b_3[0]` is NOT referring to `a_3[2]`, as it would have been, without the .clone()
	println(a_3) // [0, 1, 2, 3, 4, 5]
	println(b_3) // [7, 3]
	
	// negative indexing starts from the end of the array towards the start: -3 is equal to array.len - 3
	// negative slices have a different syntax from normal slices
	// you need to add a gate between the array name and the square bracket: a#[..-3]
	a_4 := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
	println(a_4#[-3..]) // [7, 8, 9]
	println(a_4#[-20..]) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
	println(a_4#[-20..-8]) // [0, 1]
	println(a_4#[..-3]) // [0, 1, 2, 3, 4, 5, 6]

	// empty arrays
	println(a_4#[-20..-10]) // []
	println(a_4#[20..10]) // []
	println(a_4#[20..30]) // []
}
